#include <cstdlib>
#include <iostream>
#include "Common/Common.h"
#include "Common/Common.h"
#include "Core/Core.h"
#include "Physics/Physics.h"
//#include "Sound/Sound.h"

#include "Engine/Scene.h"
#include "Engine/Camera.h"
#include "Engine/Initializer.h"

#include "Logic/Factory.h"
#include "Logic/Creature/Creature.h"
#include "Logic/Creature/Detail.h"
#include "Logic/Map/Ground.h"

#include <map>
#include <string>

using namespace std;
using namespace core;

static void ShowFPS( float dt )
{
	printf( "FPS = %4.2f\r", 1.0f / dt );
}

static float GetDT( )
{
	static float t0 = 0.0f;
	static float t1 = 0.0f;

	static const float MAX_DT = 0.015f;
	t0 = t1;
	t1 = Framework::GetTime( );
	float dt = float(t1 - t0 );
	return dt < MAX_DT ? dt : MAX_DT;
}

void Init( );
void MainLoop( float dt );
void Close( );

Scene* scene;

std::map<std::string, std::string> _map;

void TestMap(std::string key, std::string val)
{
	std::map<std::string, std::string>::iterator it = _map.find(key.c_str());
	if(it != _map.end())
		printf("key %s WAS found in cache\n", (*it).first.c_str());
	else
	{
		printf("key %s WAS NOT found in cache\n", key.c_str());
		_map[key.c_str()] = val;
	}
}


int main( int, char** )
{
//	TestMap("keyXX", "ValYY");
//	TestMap("keyXX", "ValYY");
//	TestMap("keyXX", "ValYY");
//	TestMap("keyXX", "ValYY");


	try
	{
		Init( );

		while( scene->IsActive( ) )
		{
			MainLoop( GetDT( ) );
		}

		Close( );
		return 0;
	}
	catch(const std::exception& ex)
	{
		printf(ex.what());
		return 0;
	}
}

void Init( )
{
	Framework::Create( );
	Window::Create( Point( 100, 100 ), Size( 800, 600 ), "Title", Window::Windowed, Color::BLACK );

	Window::Open( );
	physics::Physics::CreateEngine( Vec2( 0.0f, -9.8f ) );
//	sound::SoundEngine::Create( );

//	core::Keyboard::AddListener( camera );
	Initializer initializer;
	scene = initializer.Initialize("Scene.json");
}

void MainLoop( float dt )
{
	scene->Update( dt );
	scene->Render( );

	Window::Update( );
	ShowFPS( dt );
}

void Close( )
{
//	sound::SoundEngine::Destroy( );
	physics::Physics::DestroyEngine( );
	Window::Close( );

	delete scene;

	Window::Destroy( );
	Framework::Destroy( );
}
